/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.rpc.syncUser.user;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.impl.move.AbstractMoveService;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.rbac.exception.CompanyException;
import com.je.rbac.exception.DepartmentException;
import com.je.rbac.model.syncdata.SyncDepartment;
import com.je.rbac.rpc.SyncDeptDataRpcService;
import com.je.rbac.rpc.syncUser.util.StreamEx;
import com.je.rbac.rpc.syncUser.util.SyncParserUserUtil;
import com.je.rbac.service.IconType;
import com.je.rbac.service.company.RbacDepartmentService;
import com.je.rbac.service.remove.CompanyDeptMoveService;
import org.apache.servicecomb.provider.pojo.RpcSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RpcSchema(schemaId = "syncDeptDataRpcService")
public class SyncDeptDataRpcServiceImpl implements SyncDeptDataRpcService {

    @Autowired
    private CompanyDeptMoveService companyDeptMoveService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private MetaService metaService;
    @Autowired
    private RbacDepartmentService rbacDepartmentService;

    private final static ExecutorService EXECUTORS = Executors.newFixedThreadPool(5);
    private static DynaBean syncUserLogDynaBean;
    private final static String TYPE = "dept";

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public BaseRespResult syncDepartmentData(List<SyncDepartment> deptData) {
        //拿到所有部门数据先插入最顶级数据，然后递归插入子节点数据
        try {
            if (deptData == null || deptData.size() == 0) {
                return BaseRespResult.errorResult("部门数据为空，请检查！");
            }
            if (StreamEx.checkCFNumByDeptId(deptData) > 0) {
                return BaseRespResult.errorResult("JE_RBAC_DEPARTMENT_ID 主键字段重复，请检查！");
            }

            //每同步一次生成一次记录日志
            syncUserLogDynaBean = new DynaBean("JE_RBAC_SYNC_LOG", false);
            //日志类型为user
            syncUserLogDynaBean.setStr("LOG_CZLX", TYPE);

            Object obj = new Object();
            for (SyncDepartment eachSyncBean : deptData) {
                DynaBean eachBean = SyncParserUserUtil.buildDynaBean(eachSyncBean);
                syncUserLogDynaBean.setStr("LOG_TBSFCG", "1");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("部门名称", eachBean.getStr(""));
                jsonObject.put("部门Id", eachBean.getStr("JE_RBAC_DEPARTMENT_ID"));

                EXECUTORS.execute(() -> {
                    synchronized (obj) {
                        try {
                            if (Strings.isNullOrEmpty(eachSyncBean.getSyParent())) {
//                                return BaseRespResult.errorResult("SY_PARENT 字段不允许为空，请检查！");
                                syncUserLogDynaBean.setStr("LOG_TBSFCG", "0");
                                jsonObject.put("失败原因", "SY_PARENT 字段为空");
                                if (syncUserLogDynaBean.getStr("LOG_SBYY") != null) {
                                    if (!syncUserLogDynaBean.getStr("LOG_SBYY").contains("SY_PARENT 字段为空")) {
                                        syncUserLogDynaBean.setStr("LOG_SBYY", syncUserLogDynaBean.getStr("LOG_SBYY") + "," + "SY_PARENT 字段为空");
                                    }
                                } else {
                                    syncUserLogDynaBean.setStr("LOG_SBYY", "SY_PARENT 字段为空");
                                }
                                if (syncUserLogDynaBean.getStr("LOG_SBXX") != null) {
                                    if (!syncUserLogDynaBean.getStr("LOG_SBXX").contains(jsonObject.toJSONString())) {
                                        syncUserLogDynaBean.setStr("LOG_SBXX", syncUserLogDynaBean.getStr("LOG_SBXX") + "," + jsonObject.toJSONString());
                                    }
                                } else {
                                    syncUserLogDynaBean.setStr("LOG_SBXX", jsonObject.toJSONString());
                                }
                                return;
                            }
                            if ("ROOT".equals(eachSyncBean.getSyParent())) {

                                if (!rbacDepartmentService.checkDeptCodeUnique(eachBean)) {
                                    syncUserLogDynaBean.setStr("LOG_TBSFCG", "0");
                                    jsonObject.put("失败原因", "组织编码重复");
                                    if (syncUserLogDynaBean.getStr("LOG_SBYY") != null) {
                                        if (!syncUserLogDynaBean.getStr("LOG_SBYY").contains("组织编码重复")) {
                                            syncUserLogDynaBean.setStr("LOG_SBYY", syncUserLogDynaBean.getStr("LOG_SBYY") + "," + "组织编码重复");
                                        }
                                    } else {
                                        syncUserLogDynaBean.setStr("LOG_SBYY", "组织编码重复");
                                    }
                                    if (syncUserLogDynaBean.getStr("LOG_SBXX") != null) {
                                        if (!syncUserLogDynaBean.getStr("LOG_SBXX").contains(jsonObject.toJSONString())) {
                                            syncUserLogDynaBean.setStr("LOG_SBXX", syncUserLogDynaBean.getStr("LOG_SBXX") + "," + jsonObject.toJSONString());
                                        }
                                    } else {
                                        syncUserLogDynaBean.setStr("LOG_SBXX", jsonObject.toJSONString());
                                    }
//                                    return BaseRespResult.errorResult("组织编码重复，请修改！");
                                    return;
                                }
                                DynaBean bean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", eachBean.getStr("JE_RBAC_DEPARTMENT_ID")));
                                if (bean == null) {
                                    //设置树形上级字段，此处顶级部门上级为 所属公司id
                                    eachBean.setStr("DEPARTMENT_PARENT", eachBean.getStr("SY_COMPANY_ID"));
                                    buildDeptBeanTreeInfo(eachBean);
                                    metaService.insert(eachBean);
                                } else {
                                    //如果存在，则更新数据基本信息
//                        metaService.update(eachBean);
                                    //此处如果数据已经存在，则放在处理层级逻辑中，更新基本数据；方便对比层级变化。
                                }
                                //递归处理子节点
                                recursiveUpdateBeanInfo(eachBean, eachSyncBean.getChildList());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
//                            return BaseRespResult.errorResult(e.getMessage());
                        }
                    }
                });
            }
            //处理层级逻辑
            processLevel(deptData);
        } catch (Exception e) {
            return BaseRespResult.errorResult(e.getMessage());
        }
        return BaseRespResult.successResult("操作成功！");
    }

    @Transactional(rollbackFor = {Exception.class})
    public void recursiveUpdateBeanInfo(DynaBean parentBean, List<SyncDepartment> syncChildList) throws Exception {
        if (syncChildList == null || syncChildList.size() == 0) {
            return;
        }
        for (SyncDepartment eachSyncBean : syncChildList) {
            DynaBean eachBean = SyncParserUserUtil.buildDynaBean(eachSyncBean);

            if (!parentBean.getStr("JE_RBAC_DEPARTMENT_ID").equals(eachBean.getStr("SY_PARENT"))) {
                continue;
            }
            if (!rbacDepartmentService.checkDeptCodeUnique(eachBean)) {
                throw new DepartmentException("组织编码重复，请修改！");
            }
            DynaBean bean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", eachBean.getStr("JE_RBAC_DEPARTMENT_ID")));
            if (bean == null) {
                //设置树形上级字段，此处部门上级为 上级部门id
                eachBean.setStr("DEPARTMENT_PARENT", parentBean.getStr("JE_RBAC_DEPARTMENT_ID"));
                //设置上级部门名称
                eachBean.setStr("SUPERIOR_DEPARTMENT", parentBean.getStr("DEPARTMENT_NAME"));
                buildDeptBeanTreeInfo(eachBean);
                metaService.insert(eachBean);
            } else {
                //如果存在，则更新数据基本信息
//                metaService.update(eachBean);
                //此处如果数据已经存在，则放在处理层级逻辑中，更新基本数据；方便对比层级变化。
            }

            recursiveUpdateBeanInfo(eachBean, eachSyncBean.getChildList());
        }
    }


    /***
     *构建部门树形信息
     * @param dynaBean
     */
    public void buildDeptBeanTreeInfo(DynaBean dynaBean) throws Exception {
        if (Strings.isNullOrEmpty(dynaBean.getStr("SY_COMPANY_ID"))) {
            throw new DepartmentException("请选择上级公司！");
        }
        int currentChildCount = 0;
        List<Map<String, Object>> currentChildList = metaService.selectSql("SELECT MAX(SY_ORDERINDEX) AS MAX_COUNT FROM JE_RBAC_VCOMPANYDEPT WHERE SY_PARENT = {0}", dynaBean.getStr("DEPARTMENT_PARENT"));
        if (currentChildList.size() > 0) {
            currentChildCount = (int) currentChildList.get(0).get("MAX_COUNT");
        }

        int userOrderCount = 10000;
        List<Map<String, Object>> userOrderList = metaService.selectSql("SELECT MAX(DEPARTMENT_USER_ORDERINDEX) AS MAX_COUNT FROM JE_RBAC_DEPARTMENT");
        if (userOrderList.size() > 0) {
            userOrderCount = Integer.valueOf(userOrderList.get(0).get("MAX_COUNT").toString());
        }
        if (!Strings.isNullOrEmpty(dynaBean.getStr("SY_COMPANY_ID")) && Strings.isNullOrEmpty(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
            //上级为公司
            //判断公司状态，若公司状态为禁用 则不可新增
            DynaBean companyBean = metaService.selectOne("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID", dynaBean.getStr("SY_COMPANY_ID")));
            if (companyBean == null) {
                throw new DepartmentException("上级部门不存在，请重新选择！");
            }
            //校验状态
            if (companyBean.getStr("SY_STATUS").equals("0")) {
                throw new DepartmentException("上级公司已被禁用！");
            }
            metaService.executeSql("UPDATE JE_RBAC_COMPANY SET SY_NODETYPE='GENERAL' WHERE JE_RBAC_COMPANY_ID = {0}", companyBean.getStr("SY_COMPANY_ID"));

            //设置公司数据
            dynaBean.setStr("SY_COMPANY_ID", companyBean.getStr("JE_RBAC_COMPANY_ID"));
            dynaBean.setStr("SY_COMPANY_NAME", companyBean.getStr("COMPANY_NAME"));
            dynaBean.setStr("SY_GROUP_COMPANY_ID", companyBean.getStr("SY_GROUP_COMPANY_ID"));
            dynaBean.setStr("SY_GROUP_COMPANY_NAME", companyBean.getStr("SY_GROUP_COMPANY_NAME"));
            //公司下添加部门，部门层级为root下级，设置树形数据
            dynaBean.set("SY_PARENT", "ROOT");
            dynaBean.set("DEPARTMENT_PARENT", companyBean.getStr("JE_RBAC_COMPANY_ID"));
            dynaBean.set("SY_PARENTPATH", "/ROOT");
            dynaBean.set("SY_LAYER", companyBean.getStr("SY_LAYER") + 1);
            dynaBean.set("SY_NODETYPE", "LEAF");
            dynaBean.set("PARENT_NODETYPE", "company");
            dynaBean.set("SY_PATH", companyBean.getStr("SY_PATH") + "/" + dynaBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            dynaBean.set("SY_TREEORDERINDEX", companyBean.getStr("SY_TREEORDERINDEX") + String.format("%06d", currentChildCount + 1));
        } else if (!Strings.isNullOrEmpty(dynaBean.getStr("SY_COMPANY_ID")) && !Strings.isNullOrEmpty(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
            //上级为部门，若部门状态为禁用 则不可新增
            DynaBean parentDeptBean = rbacDepartmentService.findById(dynaBean.getStr("SY_PARENT"));
            if (parentDeptBean == null) {
                throw new DepartmentException("不存在的上级部门，请确认上级部门是否存在！");
            }
            //校验状态
            if (parentDeptBean.getStr("SY_STATUS").equals("0")) {
                throw new DepartmentException("上级部门已被禁用！");
            }
            metaService.executeSql("UPDATE JE_RBAC_DEPARTMENT SET SY_NODETYPE='GENERAL' WHERE JE_RBAC_DEPARTMENT_ID = {0}", parentDeptBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            //设置上级部门数据，设置树形数据

            //设置公司数据
            dynaBean.setStr("SY_COMPANY_ID", parentDeptBean.getStr("SY_COMPANY_ID"));
            dynaBean.setStr("SY_COMPANY_NAME", parentDeptBean.getStr("SY_COMPANY_NAME"));
            dynaBean.setStr("SY_GROUP_COMPANY_ID", parentDeptBean.getStr("SY_GROUP_COMPANY_ID"));
            dynaBean.setStr("SY_GROUP_COMPANY_NAME", parentDeptBean.getStr("SY_GROUP_COMPANY_NAME"));
            //设置树形数据
            dynaBean.set("SY_PARENT", parentDeptBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            dynaBean.set("DEPARTMENT_PARENT", parentDeptBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            dynaBean.set("SY_PARENTPATH", parentDeptBean.getStr("SY_PATH"));
            dynaBean.set("SY_LAYER", parentDeptBean.getInt("SY_LAYER") + 1);
            dynaBean.set("SY_NODETYPE", "LEAF");
            dynaBean.set("PARENT_NODETYPE", "department");
            dynaBean.set("SY_PATH", parentDeptBean.getStr("SY_PATH") + "/" + dynaBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            dynaBean.set("SY_TREEORDERINDEX", parentDeptBean.getStr("SY_TREEORDERINDEX") + String.format("%06d", currentChildCount + 1));
        }
        dynaBean.set("SY_STATUS", "1");
        dynaBean.set("DEPARTMENT_ICON", IconType.TCONTYPE_DEPART.getVal());
        dynaBean.set("SY_ORG_ID", com.je.rbac.service.organization.OrgType.DEPARTMENT_ORG_ID.getCode());
        dynaBean.set("SY_ORDERINDEX", currentChildCount + 1);
        dynaBean.set("DEPARTMENT_USER_ORDERINDEX", userOrderCount + 10000);
        commonService.buildModelCreateInfo(dynaBean);
    }

    /***
     * 处理层级
     * @param deptData
     * @throws Exception
     */
    public void processLevel(List<SyncDepartment> deptData) throws Exception {
        for (SyncDepartment eachSyncBean : deptData) {
            if("ROOT".equals(eachSyncBean.getSyParent())) {
                DynaBean eachBean = SyncParserUserUtil.buildDynaBean(eachSyncBean);
                DynaBean sourceBean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", eachBean.getStr("JE_RBAC_DEPARTMENT_ID")));
                if (sourceBean != null) {
                    //------------处理数据层级--------------------
                    //循环查找层级变化的数据，先判断层级是否符合规则，不符合则全部回滚; 若符合则调用move方法：移动到目标公司内部
                    eachBean.setStr("DEPARTMENT_PARENT", eachBean.getStr("SY_COMPANY_ID"));
                    buildDeptBeanTreeInfo(eachBean);
                    checkAndMoveDeptCompanyInfo(sourceBean, eachBean);
                    //更新基本信息
                    metaService.update(eachBean);
                }
                //递归处理子节点
                recursiveProcessLevelInfo(eachBean, eachSyncBean.getChildList());
            }
        }
    }

    public void checkAndMoveDeptCompanyInfo(DynaBean sourceDeptBean, DynaBean dynaBean) throws DepartmentException {
        if (sourceDeptBean.getStr("SY_COMPANY_ID").equals(dynaBean.getStr("SY_COMPANY_ID")) &&
                sourceDeptBean.getStr("SUPERIOR_DEPARTMENT").equals(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
            return;
        }
        String id = sourceDeptBean.getStr("JE_RBAC_DEPARTMENT_ID");
        String toId = "";
        String place = AbstractMoveService.INSIDE;
        if (!sourceDeptBean.getStr("SY_COMPANY_ID").equals(dynaBean.getStr("SY_COMPANY_ID"))) {
            toId = dynaBean.getStr("SY_COMPANY_ID");
            if (!sourceDeptBean.getStr("SUPERIOR_DEPARTMENT").equals(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
                if (!Strings.isNullOrEmpty(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
                    toId = dynaBean.getStr("SY_PARENT");
                }
            }
        } else if (sourceDeptBean.getStr("SY_COMPANY_ID").equals(dynaBean.getStr("SY_COMPANY_ID"))) {
            DynaBean newDeptBean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", dynaBean.getStr("SY_PARENT")));
//            DynaBean newDeptBean = findById(dynaBean.getStr("SY_PARENT"));
            toId = sourceDeptBean.getStr("SY_COMPANY_ID");
            //同公司，部门改变；则需判断所选部门是否是原部门的下级；
            if (!sourceDeptBean.getStr("SUPERIOR_DEPARTMENT").equals(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
                if (!Strings.isNullOrEmpty(dynaBean.getStr("SUPERIOR_DEPARTMENT"))) {
                    if (newDeptBean.getStr("SY_PATH").indexOf(id) != -1) {
                        //下级不允许移动
                        throw new DepartmentException("不允许修改为当前部门的下级，请检查！");
                    } else {
                        toId = dynaBean.getStr("SY_PARENT");
                    }
                }
            }
        }
        //若上级部门不为空，则判断与原数据是否一致，不一致 则目标节点为上级部门
        //若上级部门为空，则判断若与原数据一致，则判断公司是否一致，不一致则目标节点为所属公司
        //若与原数据不一致，则目标节点为上级部门，
        //若目标节点为部门，则判断是否是下级部门，若 是 则不处理，返回提示

        if (!Strings.isNullOrEmpty(toId)) {
            DynaBean moveDynaBean = new DynaBean("", false);
            moveDynaBean.put("id", id);
            moveDynaBean.put("toId", toId);
            moveDynaBean.put("place", place);
            companyDeptMoveService.move(moveDynaBean);
        }
    }

    /***
     * 层级移动校验
     * @param sourceBean
     * @param eachBean
     * @throws CompanyException
     */
    public void checkDepartmentLevel(DynaBean sourceBean, DynaBean eachBean) throws CompanyException {
        DynaBean newParentBean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", eachBean.getStr("SY_PARENT")));
        if ("ROOT".equals(newParentBean.getStr("SY_PARENT"))) {
            throw new CompanyException("当前数据: " + eachBean.getStr("DEPARTMENT_NAME") + " 不能移动到公司外面！");
        }
    }

    @Transactional(rollbackFor = {Exception.class})
    public void recursiveProcessLevelInfo(DynaBean parentBean, List<SyncDepartment> syncChildList) throws Exception {
        if (syncChildList == null || syncChildList.size() == 0) {
            return;
        }
        for (SyncDepartment eachSyncBean : syncChildList) {
            DynaBean eachBean = SyncParserUserUtil.buildDynaBean(eachSyncBean);
            if (!parentBean.getStr("JE_RBAC_DEPARTMENT_ID").equals(eachBean.getStr("SY_PARENT"))) {
                continue;
            }
            DynaBean sourceBean = metaService.selectOne("JE_RBAC_DEPARTMENT", ConditionsWrapper.builder().eq("JE_RBAC_DEPARTMENT_ID", eachBean.getStr("JE_RBAC_DEPARTMENT_ID")));
            if (sourceBean != null) {
                if (!sourceBean.getStr("SY_PARENT").equals(eachBean.getStr("SY_PARENT"))) {
                    //------------处理数据层级--------------------
                    //循环查找层级变化的数据，先判断层级是否符合规则，不符合则全部回滚; 若符合则调用move方法：移动到目标公司内部
                    //设置树形上级字段，此处部门上级为 上级部门id
                    eachBean.setStr("DEPARTMENT_PARENT", parentBean.getStr("JE_RBAC_DEPARTMENT_ID"));
                    //设置上级部门名称
                    eachBean.setStr("SUPERIOR_DEPARTMENT", parentBean.getStr("DEPARTMENT_NAME"));
                    buildDeptBeanTreeInfo(eachBean);
                    checkAndMoveDeptCompanyInfo(sourceBean, eachBean);
                }
                //更新基本信息
                metaService.update(eachBean);
            }
            recursiveProcessLevelInfo(eachBean, eachSyncBean.getChildList());
        }
    }
}
